﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Core;
using Microsoft.Win32;
using ExceedMaximumAccessException = WeiBeeCommon.Core.ExceedMaximumAccessException;
using Result = WeiBeeCommon.Core.Result;
using Utility = WeiBeeCommon.Core.Utility;
using WeiBeeQQ = WeiBeeCommon.Core.WeiBeeQQ;
using WeiBeeSina = WeiBeeCommon.Core.WeiBeeSina;
using WeiBeeSohu = WeiBeeCommon.Core.WeiBeeSohu;
using WeiBeeCommon.Helpers;

namespace Pages
{
    public partial class MainWindow : IDisposable
    {
        readonly BackgroundWorker _bgwFriendsTimeLine = new BackgroundWorker();
        readonly BackgroundWorker _bgwMyStatus = new BackgroundWorker();
        readonly BackgroundWorker _bgwUpdateStatus = new BackgroundWorker();
        readonly BackgroundWorker _bgwAddFriends = new BackgroundWorker();
        readonly BackgroundWorker _bgwUpdatePictureStatus = new BackgroundWorker();
        readonly BackgroundWorker _bgwSohuVisit = new BackgroundWorker();
        readonly BackgroundWorker _bgwSinaVisit = new BackgroundWorker();
        
        
        System.Windows.Forms.NotifyIcon _NotifyIcon = new System.Windows.Forms.NotifyIcon();
        System.Windows.Forms.Timer _statusTimer;

        System.Windows.Forms.Timer _sohuVisitTimer;

        WebBrowser _wb = new WebBrowser();

        WeiBeeSohu _sohu = new WeiBeeSohu();
        WeiBeeQQ   _qq = new WeiBeeQQ();
        WeiBeeSina _sina = new WeiBeeSina();

        // Keep track of the last tweet id to check to new tweets
        Int64 _lLastId;

        public MainWindow() {
            InitializeComponent();

            SetupNotifyIcon();

            // Setup global error handler
            Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
        }

        #region Events

        void Current_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) {
            // Display and animate the error message button
            string sMessage;

            if (e.Exception.InnerException == null)
                sMessage = e.Exception.Message;
            else
                sMessage = e.Exception.InnerException.Message;

            btnError.Content = sMessage;
            btnError.ToolTip = sMessage;

            if (btnError.Height == 0) {
                var sb = (System.Windows.Media.Animation.Storyboard)FindResource("DisplayError");
                sb.Begin();
            }

            e.Handled = true;
        }

        private void BtnErrorClick(object sender, RoutedEventArgs e) {
            var sb = (System.Windows.Media.Animation.Storyboard)FindResource("HideError");
            sb.Begin();
        }

        private void BtnRefreshClick(object sender, RoutedEventArgs e) {
            BgwFriendsTimeLineStart();
        }

        private void BtnSettingsClick(object sender, RoutedEventArgs e) {
            SinaAccountSetup();
            SohuAccountSetup();
            QQAccountSetup();


            // If the settings have been modified then setup again
            //if (OriginalQQToken != SettingHelper.Token) {
                GetOAuthSettings();
                BgwFriendsTimeLineStart();
                //bgwMyStatus_Start();
            //}
        }

        private void TxtStatusTextChanged(object sender, TextChangedEventArgs e) {
            UpdateStatusButtons(true);
        }

        private void BtnUpdateStatusClick(object sender, RoutedEventArgs e) 
        {
            // Hack, hack, secrect command "add"
            if (string.Compare(txtStatus.Text, "add", true) == 0)
            {
                this.Title = "微波小蜜蜂，收听更多用户中，每15秒中增加一个。。。";
                if (!_bgwAddFriends.IsBusy) _bgwAddFriends.RunWorkerAsync();
            }
            else if (string.IsNullOrEmpty(_picturefilename))
            {
                UpdateStatusStart(_bgwUpdateStatus);
            }
            else
            {
                UpdateStatusStart(_bgwUpdatePictureStatus);
            }
        }

        private void BtnCancelUpdateClick(object sender, RoutedEventArgs e) {
            UpdateStatusButtons(false);
        }

        private void Hyperlink_RequestNavigate(object sender, RoutedEventArgs e) {
            using (var p = new System.Diagnostics.Process()) {
                var link = (Hyperlink)sender;
                p.StartInfo.FileName = link.NavigateUri.AbsoluteUri;
                p.Start();
            }
        }

        private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e) {
            // Sina Check for user settings before settings up form
            if (String.IsNullOrEmpty(SettingHelper.Token))
            {
                SinaAccountSetup();
            }
            if (String.IsNullOrEmpty(SettingHelper.QQToken))
            {
                QQAccountSetup();
            }
            if (String.IsNullOrEmpty(SettingHelper.SohuToken))
            {
                SohuAccountSetup();
            }
            Setup();
        }

        public void SohuAccountSetup()
        {
            Settings target = new Settings(_sohu.OAuth);
            target.ShowDialog();
        }

        public void QQAccountSetup()
        {
            Settings target = new Settings(_qq.OAuth);
            target.ShowDialog();
        }

        public static void SinaAccountSetup()
        {
            SinaUser sinaUserForm = new SinaUser();
            sinaUserForm.ShowDialog();
        }

        private void window_Closing(object sender, CancelEventArgs e) {
            this.Dispose();
        }

        private void window_StateChanged(object sender, EventArgs e) {
            if (this.WindowState == WindowState.Minimized)
                this.Hide();
        }

        void StatusTimer_Tick(object sender, EventArgs e) {
            BgwFriendsTimeLineStart();
            BgwMyStatusStart();
        }

        #endregion

        #region BackgroundWorker Methods

        // Friends Timeline worker methods
        void BgwFriendsTimeLineStart() {
            if (!_bgwFriendsTimeLine.IsBusy) {
                this.Title = "微波小蜜蜂 - 小蜜蜂正采粉中...";
                _bgwFriendsTimeLine.RunWorkerAsync();
            }
        }

        void BgwFriendsTimeLineDoWork(object sender, DoWorkEventArgs e) 
        {
            List<Result> results = new List<Result>();
            if (_sina.IsEnabled)
            {
                results.AddRange(_sina.GetFriendTimelines());// WeiBeeSina.GetFriendsTimeline();
            }
            if (_sohu.IsEnabled)
            {
                results.AddRange(_sohu.GetFriendTimelines());
            }
            if (_qq.IsEnabled)
            {
                results.AddRange(_qq.HomeTimeline());
            }
            results.Sort(new ResultComparer());
            e.Result = results;
        }

        void BgwAddSohuFriends(object sender, DoWorkEventArgs e)
        {
            if (_sohu.IsEnabled)
            {
                while (true)
                {
                    try
                    {
                        e.Result = _sohu.AddFavorFromFansList(_sohu.GetUserId());// WeiBeeSina.GetFriendsTimeline();
                    }
                    catch (ExceedMaximumAccessException ex)
                    {
                        Console.WriteLine("{0}", ex.Message);
                        double sleepMilliseconds = _sohu.RestDateTime.Subtract(DateTime.Now).TotalMilliseconds;
                        System.Threading.Thread.Sleep((int)sleepMilliseconds);
                    }
                    catch (Exception ex) // catch any exception and sleep 1 minute to restart
                    {

                    }
                }
            }
        }

        void SohuVisitTimer_Tick(object sender, EventArgs e)
        {
            if (!_bgwSohuVisit.IsBusy)
            {
                _bgwSohuVisit.RunWorkerAsync();
            }
        }
        void BgwFriendsTimeLineCompleted(object sender, RunWorkerCompletedEventArgs e) {
            this.Title = "微波小蜜蜂 QQ1800@GMAIL.COM 13466639769";

            List<Result> results = e.Result as List<Result>;
            if (results !=null && results.Count>0) 
            {
                HandleResults(results);

                if (btnError.Height > 0) {
                    var sb = (System.Windows.Media.Animation.Storyboard)this.FindResource("HideError");
                    sb.Begin();
                }
            }
        }

        // My Status worker methods
        void BgwMyStatusStart() {
            if (!_bgwMyStatus.IsBusy)
                _bgwMyStatus.RunWorkerAsync();
        }

        void BgwMyStatusDoWork(object sender, DoWorkEventArgs e) {
            e.Result = WeiBeeSina.GetUserInfo();
        }

        void BgwMyStatusCompleted(object sender, RunWorkerCompletedEventArgs e) {
            if (e.Result != null) {
                Result MyInfo = (Result)e.Result;
                txtStatus.TextChanged -= TxtStatusTextChanged;
                txtStatus.Text = MyInfo.Text;
                txtStatus.TextChanged += TxtStatusTextChanged;
                imgProfile.Source = new BitmapImage(new Uri(MyInfo.ProfileImageUrl));
            }
        }

        // Update status worker methods
        void UpdateStatusStart(BackgroundWorker bgworker)
        {
            if (!bgworker.IsBusy)
            {
                this.Title = "微波小蜜蜂 - 小蜜蜂正授粉中...";
                message = txtStatus.Text;
                bgworker.RunWorkerAsync();
            }
        }

        string message;
        void UpdateStatusDoWork(object sender, DoWorkEventArgs e)
        {            
            message = Utility.ReplaceUrlWithShorten(message);
            if (message.Length <= 140 && _sina.IsEnabled) _sina.AddTwitter(message);
            if (message.Length <= 140 && _qq.IsEnabled) _qq.AddTwitter(message);
            // if(message.Length<=140) 
            if ( _sohu.IsEnabled) _sohu.AddTwitter(message);
            //e.Result = _sina.GetFriendTimelines();// WeiBeeSina.GetFriendsTimeline();
        }

        void UpdateStatusPictureDoWork(object sender, DoWorkEventArgs e)
        {
            if (string.IsNullOrEmpty(message)) message = @"发图片";
            message = Utility.ReplaceUrlWithShorten(message);
            if (_sohu.IsEnabled) _sohu.AddPicture(message, _picturefilename);
            if (message.Length <= 140 && _qq.IsEnabled) _qq.AddPicture(message, _picturefilename);
            if (message.Length <= 140 && _sina.IsEnabled) _sina.UpdateStatus(message, _picturefilename);
            _picturefilename = string.Empty;
            //e.Result = _sina.GetFriendTimelines();// WeiBeeSina.GetFriendsTimeline();
        }

        void UpdateStatusCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Title = "微波小蜜蜂 QQ1800@GMAIL.COM 13466639769";
            txtStatus.Text = null;
            UpdateStatusButtons(false);
        }

        #endregion

        #region Support Methods

        /// <summary> Display list of tweets inside the Grid control </summary>
        private void AddResultsToGrid(List<Result> ResultList) {
            grdTweets.RowDefinitions.Clear();
            grdTweets.Children.Clear();

            foreach (Result Status in ResultList) {
                grdTweets.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });

                // Create the text for grid
                TextBlock TextBlock = new TextBlock();
                TextBlock.Margin = new Thickness(4);
                TextBlock.TextWrapping = TextWrapping.Wrap;
                TextBlock.Inlines.AddRange(WPFHelper.CreateInlineTextWithLinks(Status.Text, Hyperlink_RequestNavigate));
                TextBlock.Inlines.Add(new Italic(new Run(Environment.NewLine + Status.CreatedAt)));
                Grid.SetColumn(TextBlock, 1);
                Grid.SetRow(TextBlock, grdTweets.RowDefinitions.Count - 1);
                grdTweets.Children.Add(TextBlock);

                // Create the profile image for grid
                Image ProfileImage = new Image();
                ProfileImage.Source = new BitmapImage(new Uri(Status.ProfileImageUrl));
                Grid.SetColumn(ProfileImage, 0);
                Grid.SetRow(ProfileImage, grdTweets.RowDefinitions.Count - 1);
                grdTweets.Children.Add(ProfileImage);
            }
        }

        /// <summary> Setup for the page to get tweets</summary>
        private void Setup() {
            GetOAuthSettings();

            // Setup timer to get friends timeline
            _statusTimer = new System.Windows.Forms.Timer();
            _statusTimer.Tick += new EventHandler(StatusTimer_Tick);
            _statusTimer.Interval = 1000 * 120;
            _statusTimer.Start();

            // Get friends timeline
            _bgwFriendsTimeLine.DoWork += new DoWorkEventHandler(BgwFriendsTimeLineDoWork);
            _bgwFriendsTimeLine.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BgwFriendsTimeLineCompleted);
            BgwFriendsTimeLineStart();

            // Set update status workthread and call back
            _bgwUpdateStatus.DoWork += UpdateStatusDoWork;
            _bgwUpdateStatus.RunWorkerCompleted += UpdateStatusCompleted;

            // Set update status with picture workthread and call back
            _bgwUpdatePictureStatus.DoWork += UpdateStatusPictureDoWork;
            _bgwUpdatePictureStatus.RunWorkerCompleted += UpdateStatusCompleted;

            _bgwAddFriends.DoWork += new DoWorkEventHandler(BgwAddSohuFriends);

            _bgwSohuVisit.DoWork += new DoWorkEventHandler(BgwSohuVisit_DoWork);
            _bgwSohuVisit.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BgwSohuVisit_RunWorkerCompleted);

            _sohuVisitTimer = new System.Windows.Forms.Timer();
            _sohuVisitTimer.Tick += new EventHandler(SohuVisitTimer_Tick);
            _sohuVisitTimer.Interval = 60013; // One Mintues to do, find an odd number
            _sohuVisitTimer.Start();

            _bgwSinaVisit.DoWork += new DoWorkEventHandler(BgwSinaVisit_DoWork);
            _sinaVisitByComment = new System.Windows.Forms.Timer();
            _sinaVisitByComment.Tick += new EventHandler(_sinaVisitByComment_Tick);
            _sinaVisitByComment.Interval = 60013;
            _sinaVisitByComment.Start();
        }

        BatchComment batchComment;
        void BgwSinaVisit_DoWork(object sender, DoWorkEventArgs e)
        {
            if (_sina.IsEnabled)
            {
                if (batchComment == null)
                {
                    batchComment = new BatchComment(_sina);
                }
                batchComment.Comment();
            }
        }
        void BgwSohuVisit_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (_sohu.IsEnabled)
            {
                if (_sohu.IsUserIdListReady && !_sohu.IsNavigating)
                {
                    _sohu.DoNavigate();
                }
            }
        }

        void BgwSohuVisit_DoWork(object sender, DoWorkEventArgs e)
        {
            if (_sohu.IsEnabled)
            {
                //_sohu.VisitFromFollowers();
                _sohu.BatchVisitMain();
            }
        }
        public void GetOAuthSettings() {
            _sina.OAuth.Token = SettingHelper.Token;
            _sina.OAuth.TokenSecret = SettingHelper.TokenSecret;

            _qq.OAuth.Token = SettingHelper.QQToken;
            _qq.OAuth.TokenSecret = SettingHelper.QQTokenSecret;

            _sohu.OAuth.Token = SettingHelper.SohuToken;
            _sohu.OAuth.TokenSecret = SettingHelper.SohuTokenSecret;
        }

        /// <summary> Check for new tweets, and display if there are any </summary>
        void HandleResults(List<Result> ResultList) {
            // Check to see if there are new tweets
            Int64 lLastId = Convert.ToInt64(ResultList[0].ID);

            if (_lLastId != lLastId) {
                AddResultsToGrid(ResultList);

                // New tweets have been found display the alert form
                if (_lLastId != 0) {
                    Alert Alert = new Alert(SettingHelper.MessageNewTweets, SettingHelper.TweetyIconUriString, RestoreWindow);
                }
            }

            _lLastId = lLastId;
        }

        private void RestoreWindow() {
            if (this.WindowState == WindowState.Minimized) {
                this.Show();
                this.WindowState = WindowState.Normal;
            } else {
                this.WindowState = WindowState.Normal;
                NativeMethods.ShowWindowTopMost(window);
            }
        }

        private void SetupNotifyIcon() {
            _NotifyIcon.Text = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
            Uri TweetyUri = new Uri(SettingHelper.TweetyIconUriString);
            System.IO.Stream IconStream = Application.GetResourceStream(TweetyUri).Stream;
            _NotifyIcon.Icon = new System.Drawing.Icon(IconStream);
            _NotifyIcon.Click += new EventHandler((o, e) => RestoreWindow());
            _NotifyIcon.Visible = true;
        }

        private void UpdateStatusButtons(bool SetVisible) {
            if (SetVisible) {
                btnUpdateStatus.Visibility = Visibility.Visible;
                btnCancelUpdate.Visibility = Visibility.Visible;
                btnSettings.Visibility = Visibility.Hidden;
            } else {
                btnUpdateStatus.Visibility = Visibility.Hidden;
                btnCancelUpdate.Visibility = Visibility.Hidden;
                btnSettings.Visibility = Visibility.Visible;
            }
        }

        public void Dispose() {
            _statusTimer.Dispose();
            _NotifyIcon.Dispose();
            _bgwMyStatus.Dispose();
            _bgwFriendsTimeLine.Dispose();
        }

        #endregion

        string _picturefilename = string.Empty;
        private void btnPicture_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.FileName = "picture"; // Default file name
            dlg.DefaultExt = ".jpg"; // Default file extension
            dlg.Filter = "Picture File (.jpg)|*.jpg"; // Filter files by extension

            Nullable<bool> result = dlg.ShowDialog();

            if (result == true)
            {
                _picturefilename = dlg.FileName;
                UpdateStatusButtons(true);
            }
        }

        #region VisitSinaByCommentPublictimeline
        System.Windows.Forms.Timer _sinaVisitByComment;
        void _sinaVisitByComment_Tick(object sender, EventArgs e)
        {
            if (!_bgwSinaVisit.IsBusy)
            {
                _bgwSinaVisit.RunWorkerAsync();
            }
        }
        #endregion 
    }
    class ResultComparer : IComparer<Result>
    {
        #region IComparer<Result> Members
        public int Compare(Result x, Result y)
        {
            return string.Compare(y.CreatedAt, x.CreatedAt);
        }
        #endregion
    }
}
